package org.example.plugin;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.Reflector;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.example.config.thread.AfterCommitExecutor;
import org.example.entity.Worker;
import org.example.mapper.WorkerMapper;
import org.example.service.WorkerService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Component
@Slf4j
public class WorkerDataChange implements DataChangeInterface{

    @Resource
    private WorkerService workerService;

    @Resource
    private AfterCommitExecutor afterCommitExecutor;

    AtomicInteger insert = new AtomicInteger();

    AtomicInteger update = new AtomicInteger();
    AtomicInteger delete = new AtomicInteger();


    @Override
    public String namespaceName() {
        return WorkerMapper.class.getName();
    }

    @Override
    public void insert(Object parameter) {
        afterCommitExecutor.execute(()->{
            List<Map<String, Object>> maps = null;
            try {
                maps = extractInsertParam(parameter);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            List<String> names = Lists.newArrayList();
            List<String> scenes = Lists.newArrayList();
            maps.forEach(map -> {
                names.add(map.get("name").toString());
                Object scene = map.getOrDefault("scene",null);
                if( Objects.nonNull(scene) ){
                    scenes.add(scene.toString());
                }
            });
            List<Worker> list = workerService
                    .lambdaQuery()
                    .in(CollectionUtil.isNotEmpty(names) , Worker::getName, names)
                    .in(CollectionUtil.isNotEmpty(scenes),Worker::getScene,scenes)
                    .list();
            log.info("新增后第 {} 次查询 结果 : {}",insert.getAndIncrement(), JSONObject.toJSONString(list));
        });


    }

    @Override
    public void update(Object parameter) {

        afterCommitExecutor.execute(()->{

            try {
                List<Long> ids = extractUpdateParam(parameter);
                List<Worker> list = workerService.lambdaQuery().in(Worker::getId, ids)
                        .list();
                log.info("修改后第 {} 次查询结果 : {}",update.getAndIncrement(),JSONObject.toJSONString(list));
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });
    }

    @Override
    public void delete(Object parameter) {
        afterCommitExecutor.execute(()->{
            try {
                List<Long> ids = extractDeleteParam(parameter);
                log.info("第 {} 次删除 id :{}",delete.getAndIncrement(),ids);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }

        });
    }


    private List<Long> extractUpdateParam(Object parameterObject) throws IllegalAccessException {
        List<Long> ids = new ArrayList<>();
        if (parameterObject instanceof Map) {
            Map<?, ?> paramMap = (Map<?, ?>) parameterObject;
            for (Object value : paramMap.values()) {
                if (value != null) {
                    ids.addAll(extractIdsFromObject(value));
                }
            }
        } else if (parameterObject instanceof Collection) {
            Collection<?> collection = (Collection<?>) parameterObject;
            for (Object item : collection) {
                if (item != null) {
                    ids.addAll(extractIdsFromObject(item));
                }
            }
        } else {
            ids.addAll(extractIdsFromObject(parameterObject));
        }
        return ids.stream().distinct().collect(Collectors.toList());
    }

    private List<Long> extractDeleteParam(Object parameterObject) throws IllegalAccessException {
        List<Long> ids = new ArrayList<>();
        if (parameterObject instanceof Long) {
            ids.add((Long) parameterObject);
        } else if (parameterObject instanceof Collection) {
            Collection<?> collection = (Collection<?>) parameterObject;
            for (Object item : collection) {
                if (item instanceof Long) {
                    ids.add((Long) item);
                }
            }
        } else if (parameterObject instanceof Map) {
            Map<?, ?> paramMap = (Map<?, ?>) parameterObject;
            for (Object value : paramMap.values()) {
                if (value instanceof Long) {
                    ids.add((Long) value);
                } else if (value instanceof Collection) {
                    Collection<?> innerCollection = (Collection<?>) value;
                    for (Object innerItem : innerCollection) {
                        if (innerItem instanceof Long) {
                            ids.add((Long) innerItem);
                        }
                    }
                }
            }
        } else {
            ids.addAll(extractIdsFromObject(parameterObject));
        }
        return ids.stream().distinct().collect(Collectors.toList());
    }


    private List<Map<String, Object>> extractInsertParam(Object parameterObject) throws IllegalAccessException {
        List<Map<String, Object>> ids = new ArrayList<>();
        if (parameterObject instanceof Collection) {
            Collection<?> collection = (Collection<?>) parameterObject;
            for (Object item : collection) {
                if (item != null) {
                    ids.add(getObjectData(item));
                }
            }
        } else {
            ids.add(getObjectData(parameterObject));
        }
        return ids;
    }

    // 获取对象的属性和值
    private Map<String, Object> getObjectData(Object object) {
        Map<String, Object> data = new HashMap<>();
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                data.put(field.getName(), field.get(object));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return data;
    }


    private List<Long> extractIdsFromObject(Object object) throws IllegalAccessException {
        List<Long> ids = new ArrayList<>();
        try {
            MetaObject metaObject = MetaObject.forObject(object, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
            Object id = metaObject.getValue("id");
            if (id instanceof Long) {
                ids.add((Long) id);
            }
        } catch (Exception e) {
            // 若对象没有 id 字段，忽略
        }
        return ids;
    }
}
